#include "zlang_in.h"

static int SaveStackTrace( struct ZlangRuntime *rt , size_t frame_offset , struct ZlangObject *stack_trace_obj )
{
	struct ZlangObjectsStackFrame			*objs_stack_frame = NULL ;
	int						objs_stack_index ;
	int						in_param_index , in_param_count ;
	int						local_objs_index , local_objs_count ;
	struct ZlangObject				*in_param_obj = NULL ;
	struct ZlangObject				*local_obj = NULL ;
	struct ZlangObject				*tostr_obj = NULL ;
	char						*str = NULL ;
	int32_t						str_len ;
	int						nret = 0 ;
	
	CallRuntimeFunction_string_Clear( rt , stack_trace_obj );
	
	objs_stack_frame = GetCurrentLocalObjectsStackFrame( rt ) ;
	objs_stack_index = GetCurrentLocalObjectsStackFrameIndex( rt ) ;
	while( objs_stack_index >= 0 )
	{
		CallRuntimeFunction_string_AppendFormatStringValue( rt , stack_trace_obj , "FRAME %d CALLER (%s:%d,%d) - CALLEE [%s][%s] (%s:%d,%d)\n"
			, objs_stack_index+1
			, (objs_stack_frame->caller_token_info?objs_stack_frame->caller_token_info->source_filename:"null"),(objs_stack_frame->caller_token_info?objs_stack_frame->caller_token_info->source_row:0),(objs_stack_frame->caller_token_info?objs_stack_frame->caller_token_info->source_col:0)
			, GetObjectsStackInObjectName(objs_stack_frame) , GetObjectsStackFullFuncName(objs_stack_frame)
			, (objs_stack_frame->callee_token_info?objs_stack_frame->callee_token_info->source_filename:"null"),(objs_stack_frame->callee_token_info?objs_stack_frame->callee_token_info->source_row:0),(objs_stack_frame->callee_token_info?objs_stack_frame->callee_token_info->source_col:0) );
		
		in_param_count = GetInputParameterCountInStackFrame( rt , objs_stack_frame ) ;
		local_objs_count = GetLocalObjectCountInStackFrame( rt , objs_stack_frame ) ;
		
		for( in_param_index = 1 ; in_param_index <= in_param_count ; in_param_index++ )
		{
			in_param_obj = GetInputParameterInStackFrame( rt , objs_stack_frame , in_param_index ) ;
			
			if( in_param_obj->funcs_enti && in_param_obj->funcs_enti->direct_funcs && in_param_obj->funcs_enti->direct_funcs->to_string_func )
			{
				tostr_obj = CloneStringObject( rt , NULL ) ;
				if( tostr_obj == NULL )
					abort();
				
				nret = in_param_obj->funcs_enti->direct_funcs->to_string_func( rt , in_param_obj , & tostr_obj ) ;
				if( nret )
				{
					DestroyObject( rt , tostr_obj );
					abort();
				}
				
				CallRuntimeFunction_string_GetStringValue( rt , tostr_obj , & str , & str_len );
			}
			else
			{
				str = "(no_tostr_func)" ;
				str_len = (int32_t)strlen(str) ;
			}
			
			CallRuntimeFunction_string_AppendFormatStringValue( rt , stack_trace_obj , "	IN-PARAM [%s][%s] VALUE[%.*s]\n" , GetCloneObjectName(in_param_obj) , GetObjectName(in_param_obj) , str_len,str );
			
			if( in_param_obj->funcs_enti && in_param_obj->funcs_enti->direct_funcs && in_param_obj->funcs_enti->direct_funcs->to_string_func )
			{
				DestroyObject( rt , tostr_obj );
			}
		}
		
		for( local_objs_index = 1 ; local_objs_index <= local_objs_count ; local_objs_index++ )
		{
			local_obj = GetLocalObjectInStackFrame( rt , objs_stack_frame , local_objs_index ) ;
			
			if( local_obj->funcs_enti && local_obj->funcs_enti->direct_funcs && local_obj->funcs_enti->direct_funcs->to_string_func )
			{
				tostr_obj = CloneStringObject( rt , NULL ) ;
				if( tostr_obj == NULL )
					abort();
				
				nret = local_obj->funcs_enti->direct_funcs->to_string_func( rt , local_obj , & tostr_obj ) ;
				if( nret )
				{
					DestroyObject( rt , tostr_obj );
					abort();
				}
				
				CallRuntimeFunction_string_GetStringValue( rt , tostr_obj , & str , & str_len );
			}
			else
			{
				str = "(no_tostr_func)" ;
				str_len = (int32_t)strlen(str) ;
			}
			
			CallRuntimeFunction_string_AppendFormatStringValue( rt , stack_trace_obj , "	LOCAL-OBJ [%s][%s] VALUE[%.*s]\n" , GetCloneObjectName(local_obj) , GetObjectName(local_obj) , str_len,str );
			
			if( local_obj->funcs_enti && local_obj->funcs_enti->direct_funcs && local_obj->funcs_enti->direct_funcs->to_string_func )
			{
				DestroyObject( rt , tostr_obj );
			}
		}
		
		objs_stack_frame = GetPreviousObjectsStackFrame( rt , objs_stack_frame ) ;
		objs_stack_index--;
	}
	
	return 0;
}

#define exception_THROWEXCEPTION(_exception_) \
ZlangDirectFunction_##_exception_##_ThrowException _exception_##_ThrowException; \
int _exception_##_ThrowException( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t code , char *message ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	struct ZlangObjectsStackFrame			*func_stack_frame = NULL ; \
	int						nret = 0 ; \
	\
	obj_direct_prop->code = code ; \
	\
	nret = CallRuntimeFunction_string_SetStringValue( rt , obj_direct_prop->message_obj , message , STRLEN_OF_STRING ); \
	if( nret ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret ) \
		return nret; \
	} \
	\
	nret = SaveStackTrace( rt , 0 , obj_direct_prop->stack_trace_obj ); \
	if( nret ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SaveStackTrace failed[%d]" , nret ) \
		return nret; \
	} \
	\
	obj_direct_prop->exception_source_filename = rt->travel_token_info->source_filename ; \
	obj_direct_prop->exception_source_row = rt->travel_token_info->source_row ; \
	obj_direct_prop->exception_source_col = rt->travel_token_info->source_col ; \
	\
	if( obj_direct_prop->exception_obj_name ) \
	{ \
		ZLFREE( obj_direct_prop->exception_obj_name ); obj_direct_prop->exception_obj_name = NULL ; \
	} \
	if( rt->in_obj && GetObjectName(rt->in_obj) ) \
	{ \
		obj_direct_prop->exception_obj_name = ZLSTRDUP( GetObjectName(rt->in_obj) ) ; \
		if( obj_direct_prop->exception_obj_name == NULL ) \
			return ZLANG_ERROR_ALLOC; \
	} \
	\
	if( obj_direct_prop->exception_func_name ) \
	{ \
		ZLFREE( obj_direct_prop->exception_func_name ); obj_direct_prop->exception_func_name = NULL ; \
	} \
	func_stack_frame = GetFunctionLocalObjectsStackFrame( rt ) ; \
	if( func_stack_frame ) \
	{ \
		obj_direct_prop->exception_func_name = ZLSTRDUP( GetObjectsStackFullFuncName(func_stack_frame) ) ; \
		if( obj_direct_prop->exception_func_name == NULL ) \
			return ZLANG_ERROR_ALLOC; \
	} \
	\
	obj_direct_prop->thrown_flag = 1 ; \
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "obj_direct_prop->thrown_flag[%d]" , obj_direct_prop->thrown_flag ) \
	\
	if( obj == rt->frequent_objs.error_obj ) \
		return 0; \
	else \
		return code; \
} \

#define ZLANGINVOKEFUNCTION_exception_THROWEXCEPTION(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_ThrowException_int_string; \
int ZlangInvokeFunction_##_exception_##_ThrowException_int_string( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	struct ZlangObject				*in1 = GetInputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObject				*in2 = GetInputParameterInLocalObjectStack(rt,2) ; \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	struct ZlangObjectsStackFrame			*func_stack_frame = NULL ; \
	int						nret = 0 ; \
	\
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & (obj_direct_prop->code) ); \
	\
	nret = ReferObject( rt , obj_direct_prop->message_obj , in2 ) ; \
	if( nret ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SaveStackTrace failed[%d]" , nret ) \
		CallRuntimeFunction_int_SetIntValue( rt , out1 , nret ); \
		return nret; \
	} \
	\
	nret = SaveStackTrace( rt , 1 , obj_direct_prop->stack_trace_obj ); \
	if( nret ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SaveStackTrace failed[%d]" , nret ) \
		CallRuntimeFunction_int_SetIntValue( rt , out1 , nret ); \
		return nret; \
	} \
	\
	obj_direct_prop->exception_source_filename = rt->travel_token_info->source_filename ; \
	obj_direct_prop->exception_source_row = rt->travel_token_info->source_row ; \
	obj_direct_prop->exception_source_col = rt->travel_token_info->source_col ; \
	\
	func_stack_frame = GetFunctionLocalObjectsStackFrame( rt ) ; \
	func_stack_frame = GetPreviousObjectsStackFrame( rt , func_stack_frame ) ; \
	if( obj_direct_prop->exception_obj_name ) \
	{ \
		ZLFREE( obj_direct_prop->exception_obj_name ); obj_direct_prop->exception_obj_name = NULL ; \
	} \
	if( func_stack_frame && GetObjectsStackInObjectName(func_stack_frame) ) \
	{ \
		obj_direct_prop->exception_obj_name = ZLSTRDUP( GetObjectsStackInObjectName(func_stack_frame) ) ; \
		if( obj_direct_prop->exception_obj_name == NULL ) \
		{ \
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "strdup func_stack_frame in object name failed" ) \
			CallRuntimeFunction_int_SetIntValue( rt , out1 , ZLANG_ERROR_ALLOC ); \
			return ZLANG_ERROR_ALLOC; \
		} \
	} \
	if( obj_direct_prop->exception_func_name ) \
	{ \
		ZLFREE( obj_direct_prop->exception_func_name ); obj_direct_prop->exception_func_name = NULL ; \
	} \
	if( func_stack_frame && GetObjectsStackFullFuncName(func_stack_frame) ) \
	{ \
		obj_direct_prop->exception_func_name = ZLSTRDUP( GetObjectsStackFullFuncName(func_stack_frame) ) ; \
		if( obj_direct_prop->exception_func_name == NULL ) \
		{ \
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "strdup func_stack_frame full_func_name failed" ) \
			CallRuntimeFunction_int_SetIntValue( rt , out1 , ZLANG_ERROR_ALLOC ); \
			return ZLANG_ERROR_ALLOC; \
		} \
	} \
	\
	obj_direct_prop->thrown_flag = 2 ; \
	TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "obj_direct_prop->thrown_flag[%d]" , obj_direct_prop->thrown_flag ) \
	\
	CallRuntimeFunction_int_SetIntValue( rt , out1 , obj_direct_prop->code ); \
	\
	return 0; \
} \

#define exception_HAVEEXCEPTION(_exception_) \
ZlangDirectFunction_##_exception_##_HaveException _exception_##_HaveException; \
int _exception_##_HaveException( struct ZlangRuntime *rt , struct ZlangObject *obj , unsigned char *thrown_flag ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	if( thrown_flag ) \
	{ \
		if( obj_direct_prop->thrown_flag ) \
			(*thrown_flag) = TRUE ; \
		else \
			(*thrown_flag) = FALSE ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_HAVEEXCEPTION(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_HaveException; \
int ZlangInvokeFunction_##_exception_##_HaveException( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject			*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	unsigned char				thrown_flag ; \
	int					nret = 0 ; \
	\
	nret = _exception_##_HaveException( rt , obj , & thrown_flag ) ; \
	if( nret ) \
	{ \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , thrown_flag ); \
	\
	return 0; \
} \

#define exception_GETCODE(_exception_) \
ZlangDirectFunction_##_exception_##_GetCode exception_##_GetCode; \
int _exception_##_GetCode( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t *code ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	if( code ) \
	{ \
		(*code) = obj_direct_prop->code ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_GETCODE(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_GetCode; \
int ZlangInvokeFunction_##_exception_##_GetCode( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	\
	CallRuntimeFunction_int_SetIntValue( rt , out1 , obj_direct_prop->code ); \
	\
	return 0; \
} \

#define exception_GETMESSAGE(_exception_) \
ZlangDirectFunction_##_exception_##_GetMessage exception_##_GetMessage; \
int _exception_##_GetMessage( struct ZlangRuntime *rt , struct ZlangObject *obj , char **message ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	char						**buf = NULL ; \
	\
	if( message ) \
	{ \
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , obj_direct_prop->message_obj , & buf , NULL , NULL ); \
		(*message) = (*buf) ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_GETMESSAGE(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_GetMessage; \
int ZlangInvokeFunction_##_exception_##_GetMessage( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int						nret = 0 ; \
	\
	nret = ReferObject( rt , out1 , obj_direct_prop->message_obj ) ; \
	if( nret ) \
	{ \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	return 0; \
} \

#define exception_GETEXCEPTIONSOURCEFILENAME(_exception_) \
ZlangDirectFunction_##_exception_##_GetExceptionSourceFilename exception_##_GetExceptionSourceFilename; \
int _exception_##_GetExceptionSourceFilename( struct ZlangRuntime *rt , struct ZlangObject *obj , char **exception_source_filename ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	if( exception_source_filename ) \
	{ \
		(*exception_source_filename) = obj_direct_prop->exception_source_filename ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_GETEXCEPTIONSOURCEFILENAME(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_ExceptionSourceFilename; \
int ZlangInvokeFunction_##_exception_##_GetExceptionSourceFilename( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	char						*exception_source_filename = NULL ; \
	int						nret = 0 ; \
	\
	_exception_##_GetExceptionSourceFilename( rt , obj , & exception_source_filename ); \
	nret = CallRuntimeFunction_string_SetStringValue( rt , out1 , exception_source_filename , STRLEN_OF_STRING ) ; \
	if( nret ) \
	{ \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	return 0; \
} \

#define exception_GETEXCEPTIONSOURCEROW(_exception_) \
ZlangDirectFunction_##_exception_##_GetExceptionSourceRow exception_##_GetExceptionSourceRow; \
int _exception_##_GetExceptionSourceRow( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t *exception_source_row ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	if( exception_source_row ) \
	{ \
		(*exception_source_row) = obj_direct_prop->exception_source_row ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_GETEXCEPTIONSOURCEROW(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_ExceptionSourceRow; \
int ZlangInvokeFunction_##_exception_##_GetExceptionSourceRow( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int32_t						exception_source_row ; \
	\
	_exception_##_GetExceptionSourceRow( rt , obj , & exception_source_row ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , exception_source_row ) ; \
	\
	return 0; \
} \

#define exception_GETEXCEPTIONSOURCECOLUMN(_exception_) \
ZlangDirectFunction_##_exception_##_GetExceptionSourceColumn exception_##_GetExceptionSourceColumn; \
int _exception_##_GetExceptionSourceColumn( struct ZlangRuntime *rt , struct ZlangObject *obj , int32_t *exception_source_col ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	if( exception_source_col ) \
	{ \
		(*exception_source_col) = obj_direct_prop->exception_source_col ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_GETEXCEPTIONSOURCECOLUMN(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_ExceptionSourceColumn; \
int ZlangInvokeFunction_##_exception_##_GetExceptionSourceColumn( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int32_t						exception_source_col ; \
	\
	_exception_##_GetExceptionSourceColumn( rt , obj , & exception_source_col ); \
	CallRuntimeFunction_int_SetIntValue( rt , out1 , exception_source_col ) ; \
	\
	return 0; \
} \

#define exception_GETEXCEPTIONOBJECTNAME(_exception_) \
ZlangDirectFunction_##_exception_##_GetExceptionObjectName exception_##_GetExceptionObjectName; \
int _exception_##_GetExceptionObjectName( struct ZlangRuntime *rt , struct ZlangObject *obj , char **exception_obj_name ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	if( exception_obj_name ) \
	{ \
		(*exception_obj_name) = obj_direct_prop->exception_obj_name ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_GETEXCEPTIONOBJECTNAME(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_ExceptionObjectName; \
int ZlangInvokeFunction_##_exception_##_GetExceptionObjectName( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	char						*exception_obj_name = NULL ; \
	int						nret = 0 ; \
	\
	_exception_##_GetExceptionObjectName( rt , obj , & exception_obj_name ); \
	nret = CallRuntimeFunction_string_SetStringValue( rt , out1 , exception_obj_name , STRLEN_OF_STRING ) ; \
	if( nret ) \
	{ \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	return 0; \
} \

#define exception_GETEXCEPTIONFUNCTIONNAME(_exception_) \
ZlangDirectFunction_##_exception_##_GetExceptionFunctionName exception_##_GetExceptionFunctionName; \
int _exception_##_GetExceptionFunctionName( struct ZlangRuntime *rt , struct ZlangObject *obj , char **exception_func_name ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	if( exception_func_name ) \
	{ \
		(*exception_func_name) = obj_direct_prop->exception_func_name ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_GETEXCEPTIONFUNCTIONNAME(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_ExceptionFunctionName; \
int ZlangInvokeFunction_##_exception_##_GetExceptionFunctionName( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	char						*exception_func_name = NULL ; \
	int						nret = 0 ; \
	\
	_exception_##_GetExceptionFunctionName( rt , obj , & exception_func_name ); \
	nret = CallRuntimeFunction_string_SetStringValue( rt , out1 , exception_func_name , STRLEN_OF_STRING ) ; \
	if( nret ) \
	{ \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	return 0; \
} \

#define exception_GETSTACKTRACE(_exception_) \
ZlangDirectFunction_##_exception_##_GetStackTrace _exception_##_GetStackTrace; \
int _exception_##_GetStackTrace( struct ZlangRuntime *rt , struct ZlangObject *obj , char **stack_trace ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	char						**buf = NULL ; \
	\
	if( stack_trace ) \
	{ \
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , obj_direct_prop->stack_trace_obj , & buf , NULL , NULL ); \
		(*stack_trace) = (*buf) ; \
	} \
	\
	return 0; \
} \

#define ZLANGINVOKEFUNCTION_exception_GETSTACKTRACE(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_GetStackTrace; \
int ZlangInvokeFunction_##_exception_##_GetStackTrace( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	struct ZlangObject				*out1 = GetOutputParameterInLocalObjectStack(rt,1) ; \
	int						nret = 0 ; \
	\
	nret = ReferObject( rt , out1 , obj_direct_prop->stack_trace_obj ) ; \
	if( nret ) \
	{ \
		UnreferObject( rt , out1 ); \
		return 0; \
	} \
	\
	return 0; \
} \

#define exception_CLEANTHROWN(_exception_) \
ZlangDirectFunction_##_exception_##_CleanException _exception_##_CleanException; \
int _exception_##_CleanException( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	struct ZlangDirectProperty_##_exception_	*obj_direct_prop = GetObjectDirectProperty(obj) ; \
	\
	if( obj_direct_prop->thrown_flag > 0 ) \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "%s thrown_flag[%d]->[%d]" , (obj==rt->frequent_objs.error_obj?"error":"fatal") , obj_direct_prop->thrown_flag , 0 ) \
		obj_direct_prop->thrown_flag = 0 ; \
	} \
	else \
	{ \
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "%s thrown_flag[%d]" , (obj==rt->frequent_objs.error_obj?"error":"fatal") , obj_direct_prop->thrown_flag ) \
	} \
	\
	return obj_direct_prop->thrown_flag; \
} \

#define ZLANGINVOKEFUNCTION_exception_CLEANTHROWN(_exception_) \
ZlangInvokeFunction ZlangInvokeFunction_##_exception_##_CleanException; \
int ZlangInvokeFunction_##_exception_##_CleanException( struct ZlangRuntime *rt , struct ZlangObject *obj ) \
{ \
	_exception_##_CleanException( rt , obj ); \
	\
	return 0; \
} \

